package org.liujing.jsw.client.ui;

import java.util.*;
import com.google.gwt.user.client.ui.*;
import com.google.gwt.user.client.DOM;
import com.google.gwt.dom.client.Element;
import com.google.gwt.dom.client.*;
import com.google.gwt.core.client.GWT;

public class Container extends Component{

	LayoutManager layoutMgr;
	private java.util.List<Widget> component = new java.util.ArrayList<Widget>();
	
    private boolean validateRoot = false;
    
	public Container(){
		
	}
	
	

/*	  @Override
	  protected void doAttachChildren() {
	  	  ((ContainerImpl)impl).doAttachChildren();
	  }
	
	  @Override
	  protected void doDetachChildren() {
		((ContainerImpl)impl).doDetachChildren();
	  }
	  
	  @Override
	 public void onLoad(){
		super.onLoad();
		((ContainerImpl)impl).onLoad();
	}
	
	@Override
	public void onResize(){
		super.onResize();
		validate();		
	}
*/	

    
    public LayoutManager getLayout() {
		return layoutMgr;
    }

    
    public void setLayout(LayoutManager mgr) {
		layoutMgr = mgr;
		if (valid) {
			invalidate();
		}
    }

    public Component add(Component comp) {
        addImpl(comp, null, -1);
	return comp;
    }

    public Component add(String name, Component comp) {
	addImpl(comp, name, -1);
	return comp;
    }

    public Component add(Component comp, int index) {
	addImpl(comp, null, index);
	return comp;
    }
    
    public void add(Component comp, Object constraints) {
	addImpl(comp, constraints, -1);
    }

    public void add(Component comp, Object constraints, int index) {
       addImpl(comp, constraints, index);
    }
    
    public void clear(){
    	//todo
    }
    
    public void remove(int index) {

            if (index < 0  || index >= component.size()) {
                throw new ArrayIndexOutOfBoundsException(index);
            }
            Component comp = component.get(index);
	    //if (peer != null) {
	    comp.removeNotify();
	    //}
	    if (layoutMgr != null) {
		layoutMgr.removeLayoutComponent(comp);
	    }

	//    adjustListeningChildren(AWTEvent.HIERARCHY_EVENT_MASK, 
	//        -comp.numListening(AWTEvent.HIERARCHY_EVENT_MASK));
	//    adjustListeningChildren(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK,
	//	-comp.numListening(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK));
        //    adjustDescendants(-(comp.countHierarchyMembers()));

	    comp.parent = null;
            component.remove(index);

            invalidateIfValid();
            //if (containerListener != null ||
            //    (eventMask & AWTEvent.CONTAINER_EVENT_MASK) != 0 ||
            //    Toolkit.enabledOnToolkit(AWTEvent.CONTAINER_EVENT_MASK)) {
            //    ContainerEvent e = new ContainerEvent(this, 
            //                         ContainerEvent.COMPONENT_REMOVED,
            //                         comp);
            //    dispatchEvent(e);
            //}
            //
	    //comp.createHierarchyEvents(HierarchyEvent.HIERARCHY_CHANGED, comp,
		//		       this, HierarchyEvent.PARENT_CHANGED,
            //                           Toolkit.enabledOnToolkit(AWTEvent.HIERARCHY_EVENT_MASK));
	    //if (peer != null && layoutMgr == null && isVisible()) {
            //    updateCursorImmediately();
	    //}

    }
    
    public void remove(Component comp) {
	if (comp.parent == this)  {
            int index = component.indexOf(comp);
            if (index >= 0) {
                remove(index);
            }
        }
    }
    
    
    protected void addImpl(JComponent comp, Object constraints, int index) {

    	if (index > component.size() || (index < 0 && index != -1)) {
		throw new IllegalArgumentException(
			  "illegal component position");
	    }

    	if (comp.getParent() != null) {
    		comp.getParent().remove(comp);
            if (index > component.size()) {
                throw new IllegalArgumentException("illegal component position");
            }
        }

        if (index == -1) {
            component.add(comp);
	} else {
            component.add(index, comp);
	}
	comp.parent = this;
	    
    	if (valid) {
    		invalidate();
	    }
	    if(comp.isDomElementSet())
	    	this.getContentElement().appendChild(comp.getDomElement());
	    
	    comp.setParent((Container)this);
		comp.addNotify();
		if(comp.isDomElementSet()){
			Style style = comp.getDomElement().getStyle();
			style.setPosition(Style.Position.ABSOLUTE);
			style.setOverflow(Style.Overflow.HIDDEN);
		}
	    if (layoutMgr != null) {
			if (layoutMgr instanceof LayoutManager2) {
				((LayoutManager2)layoutMgr).addLayoutComponent(comp, constraints);
			} else if (constraints instanceof String) {
				layoutMgr.addLayoutComponent((String)constraints, comp);
			}
	    }
    }
    
    public JComponent getComponent(int n) {
	
        if ((n < 0) || (n >= component.size())) {
        	throw new ArrayIndexOutOfBoundsException("No such child: " + n);
	    }
        return (JComponent)component.get(n);
    }
    
    
	public boolean isValidateRoot() {
        return validateRoot;
    }
    
    public void invalidate() {
        LayoutManager layoutMgr = this.layoutMgr;
	if (layoutMgr instanceof LayoutManager2) {
	    LayoutManager2 lm = (LayoutManager2) layoutMgr;
	    lm.invalidateLayout((Container)this);
	}
	super.invalidate();
    }
    
    public void validate() {
    	if (!valid) {
    		doLayout();
            for (int i = 0; i < component.size(); i++) {
                JComponent comp = (JComponent)component.get(i);
                if (   (comp instanceof Container) ) {
                    ((Container)comp).validate();
                }
            }
		    valid = true;
		}
    }
    
    public void doLayout() {
    	GWT.log("Container.doLayout() " + this.getClass().getName());
    	LayoutManager layoutMgr = this.layoutMgr;
		if (layoutMgr != null) {
			layoutMgr.layoutContainer((Container)this);
		}
    }
    
    public int getComponentCount() {
    	return component.size();
    }
    
    @Override
    @Deprecated
    public Dimension preferredSize() {
			Dimension dim = prefSize;
			if (dim == null || !(isPreferredSizeSet() || isValid())) {
			
			prefSize = (layoutMgr != null) ?
				layoutMgr.preferredLayoutSize((Container)this) :
				super.preferredSize();
					dim = prefSize;
		}
        if (dim != null){
            return new Dimension(dim);
        }
        else{
            return dim;
        }
    
    }

    @Override
    @Deprecated
    public Dimension minimumSize() {
    	Dimension dim = minSize;
    	if (dim == null || !(isMinimumSizeSet() || isValid())) {
		minSize = (layoutMgr != null) ?
			layoutMgr.minimumLayoutSize((Container)this) :
			super.minimumSize();
				dim = minSize;
		}
		if (dim != null){
			return new Dimension(dim);
		}
		else{
			return dim;
		}
    }

    @Override
    public Dimension getMaximumSize() {
    	if (isMaximumSizeSet()) {
            return new Dimension(maxSize);
        }
    	Dimension size = null;
        if (ui != null) {
            size = ui.getMaximumSize(this);
        }
        if(size != null)
        	return size;
    	Dimension dim = maxSize;
    	if (dim == null || !(isMaximumSizeSet() || isValid())) {
	    
              if (layoutMgr instanceof LayoutManager2) {
                   LayoutManager2 lm = (LayoutManager2) layoutMgr;
                   maxSize = lm.maximumLayoutSize((Container)this);
              } else {
                   maxSize = new Dimension(Short.MAX_VALUE, Short.MAX_VALUE);
              }
              dim = maxSize;
        }
        if (dim != null){
            return new Dimension(dim);
        }
        else{
            return dim;
        }
    }

    public float getAlignmentX() {
	float xAlign;
	if (layoutMgr instanceof LayoutManager2) {
	    //synchronized (getTreeLock()) {
		LayoutManager2 lm = (LayoutManager2) layoutMgr;
		xAlign = lm.getLayoutAlignmentX((Container)this);
	   // }
	} else {
	    xAlign = super.getAlignmentX();
	}
	return xAlign;
    }


    public float getAlignmentY() {
		float yAlign;
		if (layoutMgr instanceof LayoutManager2) {
			//synchronized (getTreeLock()) {
			LayoutManager2 lm = (LayoutManager2) layoutMgr;
			yAlign = lm.getLayoutAlignmentY((Container)this);
			//}
		} else {
			yAlign = super.getAlignmentY();
		}
		return yAlign;
    }
}
